package es.buffygilmore.gastosapp;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import es.buffygilmore.gastosapp.util.HelperUtil;
import es.buffygilmore.gastosapp.vo.Evento;
import es.buffygilmore.gastosapp.vo.Gasto;
import es.buffygilmore.gastosapp.vo.Imagen;
import es.buffygilmore.gastosapp.vo.Pagador;
import es.buffygilmore.gastosapp.vo.Persona;

/**
 * Acceso a la base de datos. Operaciones CRUD. Devuelve cursores en lugar de colecciones.
 */
public class GastosAppDbAdapter {

	public static final String KEY_EVENTO_TITULO = "titulo";
	public static final String KEY_EVENTO_ROWID = "_id";

	public static final String KEY_GASTO_DESCRIPCION = "descripcion";
	public static final String KEY_GASTO_IMPORTE = "importe";
	public static final String KEY_GASTO_FECHA = "fecha";
	public static final String KEY_GASTO_EVENTO = "idEvento";
	public static final String KEY_GASTO_ROWID = "_id";

	public static final String KEY_IMAGEN_RUTA = "ruta";
	public static final String KEY_IMAGEN_GASTO = "idGasto";
	public static final String KEY_IMAGEN_ROWID = "_id";

	public static final String KEY_PERSONA_NOMBRE = "nombre";
	public static final String KEY_PERSONA_EVENTO = "idEvento";
	public static final String KEY_PERSONA_ROWID = "_id";

	public static final String KEY_PAGADOR_PERSONA = "idPersona";
	public static final String KEY_PAGADOR_GASTO = "idGasto";
	public static final String KEY_PAGADOR_ROWID = "_id";

	private static final String TAG = "GastosAppDbAdapter";
	private DatabaseHelper mDbHelper;
	private SQLiteDatabase mDb;

	/**
	 * Database creation sql statement
	 */
	private static final String DATABASE_CREATE_TABLE_EVENTO = "create table evento (_id integer primary key autoincrement, "
			+ "titulo text not null);";
	private static final String DATABASE_CREATE_TABLE_GASTO = "create table gasto (_id integer primary key autoincrement, "
			+ "descripcion text not null, importe real not null, fecha text null, idEvento integer not null);";
	private static final String DATABASE_CREATE_TABLE_IMAGEN = "create table imagen (_id integer primary key autoincrement, "
			+ "ruta text not null, idGasto integer not null);";
	private static final String DATABASE_CREATE_TABLE_PERSONA = "create table persona (_id integer primary key autoincrement, "
			+ "nombre text not null, idEvento integer not null);";
	private static final String DATABASE_CREATE_TABLE_PAGADOR = "create table pagador (_id integer primary key autoincrement, "
			+ "idGasto integer not null, idPersona integer not null);";

	private static final String DATABASE_NAME = "gastos";
	private static final String DATABASE_TABLE_EVENTO = "evento";
	private static final String DATABASE_TABLE_GASTO = "gasto";
	private static final String DATABASE_TABLE_IMAGEN = "imagen";
	private static final String DATABASE_TABLE_PERSONA = "persona";
	private static final String DATABASE_TABLE_PAGADOR = "pagador";

	private static final int DATABASE_VERSION = 1;

	private final Context mCtx;

	private static class DatabaseHelper extends SQLiteOpenHelper {

		DatabaseHelper(final Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}

		@Override
		public void onCreate(final SQLiteDatabase db) {

			db.execSQL(DATABASE_CREATE_TABLE_EVENTO);
			db.execSQL(DATABASE_CREATE_TABLE_GASTO);
			db.execSQL(DATABASE_CREATE_TABLE_IMAGEN);
			db.execSQL(DATABASE_CREATE_TABLE_PERSONA);
			db.execSQL(DATABASE_CREATE_TABLE_PAGADOR);
		}

		@Override
		public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
			Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion
					+ ", which will destroy all old data");
			db.execSQL("DROP TABLE IF EXISTS pagador");
			db.execSQL("DROP TABLE IF EXISTS persona");
			db.execSQL("DROP TABLE IF EXISTS imagen");
			db.execSQL("DROP TABLE IF EXISTS gasto");
			db.execSQL("DROP TABLE IF EXISTS evento");
			this.onCreate(db);
		}
	}

	public GastosAppDbAdapter(final Context ctx) {
		this.mCtx = ctx;
	}

	public GastosAppDbAdapter open() throws SQLException {
		this.mDbHelper = new DatabaseHelper(this.mCtx);
		this.mDb = this.mDbHelper.getWritableDatabase();
		return this;
	}

	public void close() {
		this.mDbHelper.close();
	}

	public long crearEvento(final Evento evento) {
		final ContentValues initialValues = new ContentValues();
		initialValues.put(KEY_EVENTO_TITULO, evento.getTitulo());

		return this.mDb.insert(DATABASE_TABLE_EVENTO, null, initialValues);
	}

	public boolean eliminarEvento(final long rowId) {

		return this.mDb.delete(DATABASE_TABLE_EVENTO, KEY_EVENTO_ROWID + "=" + rowId, null) > 0;
	}

	public Cursor obtenerTodosEventos() {

		return this.mDb.query(DATABASE_TABLE_EVENTO, new String[] { KEY_EVENTO_ROWID,
				KEY_EVENTO_TITULO }, null, null, null, null, null);
	}

	public Cursor obtenerEvento(final long rowId) throws SQLException {

		final Cursor mCursor =

				this.mDb.query(true, DATABASE_TABLE_EVENTO, new String[] { KEY_EVENTO_ROWID,
						KEY_EVENTO_TITULO }, KEY_EVENTO_ROWID + "=" + rowId, null, null, null, null, null);
		if (mCursor != null) {
			mCursor.moveToFirst();
		}
		return mCursor;

	}

	public boolean modificarEvento(final Evento evento) {
		final ContentValues args = new ContentValues();
		args.put(KEY_EVENTO_TITULO, evento.getTitulo());

		return this.mDb.update(DATABASE_TABLE_EVENTO, args,
				KEY_EVENTO_ROWID + "=" + evento.getId(), null) > 0;
	}

	public long crearGasto(final Gasto gasto) {
		final ContentValues initialValues = new ContentValues();
		initialValues.put(KEY_GASTO_DESCRIPCION, gasto.getDescripcion());
		initialValues.put(KEY_GASTO_IMPORTE, gasto.getImporte());
		initialValues.put(KEY_GASTO_FECHA, HelperUtil.getDateTimeToString(gasto.getFecha()));
		initialValues.put(KEY_GASTO_EVENTO, gasto.getIdEvento());

		return this.mDb.insert(DATABASE_TABLE_GASTO, null, initialValues);

	}

	public boolean eliminarGasto(final long rowId) {

		return this.mDb.delete(DATABASE_TABLE_GASTO, KEY_GASTO_ROWID + "=" + rowId, null) > 0;
	}

	public Cursor obtenerGastosPorEvento(final long idEvento) {

		return this.mDb.query(DATABASE_TABLE_GASTO, new String[] { KEY_GASTO_ROWID,
				KEY_GASTO_DESCRIPCION, KEY_GASTO_IMPORTE, KEY_GASTO_FECHA, KEY_GASTO_EVENTO },
				KEY_GASTO_EVENTO + "=" + idEvento, null, null, null, null);

	}

	public Cursor obtenerGasto(final long rowId) throws SQLException {

		final Cursor mCursor =

				this.mDb.query(true, DATABASE_TABLE_GASTO, new String[] { KEY_GASTO_ROWID,
						KEY_GASTO_DESCRIPCION, KEY_GASTO_IMPORTE, KEY_GASTO_FECHA, KEY_GASTO_EVENTO },
				KEY_GASTO_ROWID + "=" + rowId, null, null, null, null, null);
		if (mCursor != null) {
			mCursor.moveToFirst();
		}
		return mCursor;

	}

	public boolean modificarGasto(final Gasto gasto) {
		final ContentValues args = new ContentValues();
		args.put(KEY_GASTO_DESCRIPCION, gasto.getDescripcion());
		args.put(KEY_GASTO_IMPORTE, gasto.getImporte());
		args.put(KEY_GASTO_FECHA, HelperUtil.getDateTimeToString(gasto.getFecha()));
		args.put(KEY_GASTO_EVENTO, gasto.getIdEvento());

		return this.mDb.update(DATABASE_TABLE_GASTO, args, KEY_GASTO_ROWID + "=" + gasto.getId(),
				null) > 0;
	}

	public long crearImagen(final Imagen imagen) {
		final ContentValues initialValues = new ContentValues();
		initialValues.put(KEY_IMAGEN_RUTA, imagen.getRuta());
		initialValues.put(KEY_IMAGEN_GASTO, imagen.getIdGasto());

		return this.mDb.insert(DATABASE_TABLE_IMAGEN, null, initialValues);

	}

	public boolean eliminarImagen(final long rowId) {

		return this.mDb.delete(DATABASE_TABLE_IMAGEN, KEY_IMAGEN_ROWID + "=" + rowId, null) > 0;
	}

	public Cursor obtenerImagenesPorGasto(final long idGasto) {

		return this.mDb.query(DATABASE_TABLE_IMAGEN, new String[] { KEY_IMAGEN_ROWID,
				KEY_IMAGEN_RUTA, KEY_IMAGEN_GASTO }, KEY_IMAGEN_GASTO + "=" + idGasto, null, null,
				null, null);

	}

	public Cursor obtenerImagen(final long rowId) throws SQLException {

		final Cursor mCursor =

				this.mDb.query(true, DATABASE_TABLE_IMAGEN, new String[] { KEY_IMAGEN_ROWID,
						KEY_IMAGEN_RUTA, KEY_IMAGEN_GASTO }, KEY_IMAGEN_ROWID + "=" + rowId, null, null,
						null, null, null);
		if (mCursor != null) {
			mCursor.moveToFirst();
		}
		return mCursor;

	}

	public boolean modificarImagen(final Imagen imagen) {
		final ContentValues args = new ContentValues();
		args.put(KEY_IMAGEN_RUTA, imagen.getRuta());
		args.put(KEY_IMAGEN_GASTO, imagen.getIdGasto());

		return this.mDb.update(DATABASE_TABLE_IMAGEN, args,
				KEY_IMAGEN_ROWID + "=" + imagen.getId(), null) > 0;
	}

	public long crearPersona(final Persona persona) {
		final ContentValues initialValues = new ContentValues();
		initialValues.put(KEY_PERSONA_NOMBRE, persona.getNombre());
		initialValues.put(KEY_PERSONA_EVENTO, persona.getIdEvento());

		return this.mDb.insert(DATABASE_TABLE_PERSONA, null, initialValues);

	}

	public boolean eliminarPersona(final long rowId) {

		return this.mDb.delete(DATABASE_TABLE_PERSONA, KEY_PERSONA_ROWID + "=" + rowId, null) > 0;
	}

	public Cursor obtenerPersonasPorEvento(final long idEvento) {

		return this.mDb.query(DATABASE_TABLE_PERSONA, new String[] { KEY_PERSONA_ROWID,
				KEY_PERSONA_NOMBRE, KEY_PERSONA_EVENTO }, KEY_PERSONA_EVENTO + "=" + idEvento,
				null, KEY_PERSONA_NOMBRE, null, null);

	}

	public Cursor obtenerPersona(final long rowId) throws SQLException {

		final Cursor mCursor =

				this.mDb.query(true, DATABASE_TABLE_PERSONA, new String[] { KEY_PERSONA_ROWID,
						KEY_PERSONA_NOMBRE, KEY_PERSONA_EVENTO }, KEY_PERSONA_ROWID + "=" + rowId, null,
						null, null, null, null);
		if (mCursor != null) {
			mCursor.moveToFirst();
		}
		return mCursor;

	}

	public boolean modificarPersona(final Persona persona) {
		final ContentValues args = new ContentValues();
		args.put(KEY_PERSONA_NOMBRE, persona.getNombre());
		args.put(KEY_PERSONA_EVENTO, persona.getIdEvento());

		return this.mDb.update(DATABASE_TABLE_PERSONA, args,
				KEY_PERSONA_ROWID + "=" + persona.getId(), null) > 0;
	}

	public long agregarPagadorAGasto(final Pagador pagador) {
		final ContentValues initialValues = new ContentValues();
		initialValues.put(KEY_PAGADOR_GASTO, pagador.getIdGasto());
		initialValues.put(KEY_PAGADOR_PERSONA, pagador.getIdPersona());

		return this.mDb.insert(DATABASE_TABLE_PAGADOR, null, initialValues);

	}

	// TODO eliminar el id y quedarnos con la pk compuesta??
	public boolean eliminarPagadorDeGasto(final long rowId) {

		return this.mDb.delete(DATABASE_TABLE_PAGADOR, KEY_PAGADOR_ROWID + "=" + rowId, null) > 0;
	}

}
